<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Option -rectypes
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora208.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora210.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Option <TT>-rectypes</TT></H2>
<A NAME="@fonctions493"></A>With a compiler option, we can avoid this restriction to objects in cyclic
types.
<PRE>
$ ocamlc -rectypes  ...
$ ocamlopt -rectypes  ...
$ ocaml -rectypes 
</PRE>If we take up the above examples in a toplevel started with this option, here is
what we get.<BR>
<BR>


<PRE><BR># <B>type</B><CODE> </CODE><I>'a</I><CODE> </CODE>tree<CODE> </CODE><CODE>=</CODE><CODE> </CODE><I>'a</I><CODE> </CODE><CODE>*</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>tree<CODE> </CODE>list<CODE> </CODE>;;<BR><CODE>type 'a tree = 'a * 'a tree list</CODE><BR><BR># <B>let</B><CODE> </CODE><B>rec</B><CODE> </CODE>height<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>function</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE>_,[]</CODE><TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE><CODE>1</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><TT>(</TT><CODE>_,</CODE>sons<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE><CODE>1</CODE><CODE> </CODE><CODE>+</CODE><CODE> </CODE><TT>(</TT>max_list<CODE> </CODE><TT>(</TT>List.map<CODE> </CODE>height<CODE> </CODE>sons<TT>)</TT><TT>)</TT><CODE> </CODE>;;<CODE> </CODE><BR><CODE>val height : ('b * 'a list as 'a) -&gt; int = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The values <TT>tree_1</TT>, <TT>tree_2</TT> and <TT>tree_3</TT>
previously defined don't have the same type, but they all have a type
compatible with that of <TT>height</TT>.<BR>
<BR>


<PRE><BR># height<CODE> </CODE>tree_1<CODE> </CODE>;;<BR><CODE>- : int = 1</CODE><BR># height<CODE> </CODE>tree_2<CODE> </CODE>;;<BR><CODE>- : int = 2</CODE><BR># height<CODE> </CODE>tree_3<CODE> </CODE>;;<BR><CODE>- : int = 3</CODE><BR>

</PRE>
<BR>
<BR>
The keyword <B>as</B> belongs to the type language, and as such, it can be
used in a type declaration.<BR>
<BR>


<H3> Syntax </H3> <HR>


<B>type</B> <I>nom</I> <B>=</B> <I>typedef</I> <B>as</B> <B>'</B><I>var</I> <B>;;</B>



<HR>

<BR>
<BR>
We can use this syntax to define type <I>tree</I>.


<PRE><BR># <B>type</B><CODE> </CODE><I>'a</I><CODE> </CODE>tree<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><I>'a</I><CODE> </CODE><CODE>*</CODE><CODE> </CODE><I>'vertex</I><CODE> </CODE>list<CODE> </CODE><TT>)</TT><CODE> </CODE><B>as</B><CODE> </CODE><I>'vertex</I><CODE> </CODE>;;<BR><CODE>type 'a tree = 'a * 'a tree list</CODE><BR>

</PRE>
<BR>
<BR>


<H3> Warning </H3> <HR>


If this mode may be useful in some cases, it tends to accept the typing of too
many values, giving them types that are not easy to read.



<HR>

<BR>
<BR>
Without the option <TT>-rectypes</TT>, the function below would have been rejected
by the typing system.


<PRE><BR># <B>let</B><CODE> </CODE>inclus<CODE> </CODE>l1<CODE> </CODE>l2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE><B>rec</B><CODE> </CODE>mem<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>function</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>[]<CODE> </CODE>-&gt;<CODE> </CODE><B>false</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE>a::l<CODE> </CODE>-&gt;<CODE> </CODE><TT>(</TT>l<CODE>=</CODE>x<TT>)</TT><CODE> </CODE><CODE>||</CODE><CODE> </CODE><TT>(</TT>mem<CODE> </CODE>x<CODE> </CODE>a<TT>)</TT><CODE> </CODE><CODE>(* an error on purpose: a and l inverted *)</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>List.for_all<CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>-&gt;<CODE> </CODE>mem<CODE> </CODE>x<CODE> </CODE>l2<TT>)</TT><CODE> </CODE>l1<CODE> </CODE><CODE> </CODE>;;<BR><CODE>val inclus : ('a list as 'a) list list -&gt; ('b list as 'b) -&gt; bool = &lt;fun&gt;</CODE><BR>

</PRE>

Although a quick examination of the type allows to conclude to an error, we no
longer have an error message to help us locating this error.
<BR>
<BR>




<BR>
<BR>
<BR>
<BR>
<HR>
<A HREF="book-ora208.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora210.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
